Portfolio optimization is an important topic in Finance. Modern portfolio theory (MPT) states that investors are risk averse and given a level of risk, they will choose the portfolios that offer the most return. To do that we need to optimize the portfolios.

To perform the optimization we will need

So lets begin

Downloading data

First lets load our packages

# list.of.packages <- c('tidyverse','tidyquant', 'plotly','timetk','GA','xtable', 'textreadr','rvest','fGarch',"dplyr", "dygraphs", "quantmod", "TTR", 'zoo', 'tseries', 'fGarch','PEIP','tidyverse','gridExtra', 'gdata', 'xtable',"dygraphs") 
# new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
# if(length(new.packages) > 0) {install.packages(new.packages)}
# lapply(list.of.packages, require, character.only=T)

library('tidyverse')
library('tidyquant')
## Warning: package 'xts' was built under R version 4.3.3
## Warning: package 'quantmod' was built under R version 4.3.2
library('plotly')
library('timetk')
library('GA')
## Warning: package 'GA' was built under R version 4.3.2
library('xtable')
#library('textreadr')
library('rvest')
library('fGarch')
library("dplyr")
library("dygraphs")
library("quantmod")
library("TTR")
library('zoo')
library('tseries')
library('fGarch')
library('PEIP')
library('tidyverse')
library('gridExtra')
library('gdata')
library('xtable')
library("dygraphs")
# Load all the required functions needed get the results
## function to generate weight
# get_weights <- function(N){
#  return(diff(c(0, sort(runif(N-1, min = 0, max = 1)), 1)))
# }
get_weights <- function(N){
  w<- runif(N, min = 0, max = 1)
  return(w/sum(w))
}
# skewness correlation
skewrho <- function(X){
  skewrho.cor <- cor(X-mean(X), (X-mean(X))^2)
  return(skewrho.cor)
}

# sign correlation
rho.cal<-function(X){
  rho.hat<-cor(sign(X-mean(X)), X-mean(X))
  return(rho.hat)
}

# volatlity correlation
rho.vol<-function(X){
  rho.vol<-cor(abs(X-mean(X)), (X-mean(X))^2)
  return(rho.vol)
}

Simulation study for sign correlation and volatility correlation

# simulate normal, t(2), t(3), t(4), t(5)
sample <- 8000
sim.n <- rnorm (sample)     # sign correlation of a normal distribution is sqrt(2/pi)=0.7979
sim.t25 <- rt (sample, df = 2.5)
sim.t3 <- rt (sample, df = 3)
sim.t35 <- rt (sample, df = 3.5)
sim.t4 <- rt (sample, df = 4)
sim.t5 <- rt (sample, df = 5)
data <- cbind (sim.t25, sim.t3, sim.t35, sim.t4, sim.t5, sim.n)

skewrho<-apply(as.matrix(data), MARGIN=2, FUN=skewrho)
rhosign<-apply(as.matrix(data), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(data), MARGIN=2, FUN=rho.vol)

assetsummary<-data.frame(apply(data, 2, mean), apply(data, 2, sd), apply(data, 2, skewness), apply(data, 2, kurtosis), skewrho, rhovol, rhosign)
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:30:40 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & apply.data..2..mean. & apply.data..2..sd. & apply.data..2..skewness. & apply.data..2..kurtosis. & skewrho & rhovol & rhosign \\ 
##   \hline
## sim.t25 & -0.0498 & 2.0301 & -2.2919 & 75.1540 & -0.2609 & 0.7394 & 0.5924 \\ 
##   sim.t3 & 0.0106 & 1.6381 & -0.1077 & 13.1367 & -0.0277 & 0.8205 & 0.6621 \\ 
##   sim.t35 & -0.0107 & 1.5591 & -1.0251 & 32.0767 & -0.1756 & 0.6846 & 0.6765 \\ 
##   sim.t4 & -0.0012 & 1.3934 & 0.5492 & 10.9153 & 0.1528 & 0.7537 & 0.7137 \\ 
##   sim.t5 & 0.0083 & 1.2919 & 0.2128 & 4.5924 & 0.0829 & 0.8211 & 0.7425 \\ 
##   sim.n & 0.0205 & 1.0000 & -0.0026 & 0.0947 & -0.0018 & 0.9335 & 0.7943 \\ 
##    \hline
## \end{tabular}
## \end{table}

Next lets select a few stocks to build our portfolios.

We will choose some stocks.

Lets download the price data.

Portfolio selected from DD_AP_2022_lowest_average_clustering

#Import data

DD_AP_2022_lowest_average_clustering <- read.csv("~/Desktop/PO/AP/DD/2022/DD_AP_2022_lowest_average_clustering.csv")

#remove the date column
asset_prices<-DD_AP_2022_lowest_average_clustering[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##           CAT      CVX       KO      LMT      PEP        T      XOM
## [1,] 5.276894 4.675349 3.999863 5.798051 5.075427 2.771057 4.053835
## [2,] 5.329037 4.693381 4.016420 5.819354 5.076872 2.779281 4.090759
## [3,] 5.336666 4.699866 4.024679 5.808661 5.080272 2.801268 4.103119
## [4,] 5.346808 4.708339 4.019401 5.808270 5.080502 2.797446 4.126368
## [5,] 5.356669 4.722597 4.017083 5.814230 5.081767 2.831038 4.134531
## [6,] 5.345230 4.723237 4.018739 5.822829 5.082283 2.837484 4.128561
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##               CAT          CVX            KO           LMT           PEP
## [1,]  0.052143013 0.0180319769  0.0165567763  0.0213032350  0.0014442648
## [2,]  0.007628658 0.0064847584  0.0082591279 -0.0106927108  0.0034000998
## [3,]  0.010141792 0.0084732955 -0.0052779119 -0.0003909202  0.0002301584
## [4,]  0.009861644 0.0142577441 -0.0023177719  0.0059599532  0.0012645463
## [5,] -0.011439448 0.0006396038  0.0016560014  0.0085983597  0.0005167721
## [6,] -0.007654317 0.0226024268  0.0003307344  0.0024471583 -0.0004594556
##                 T          XOM
## [1,]  0.008223900  0.036924179
## [2,]  0.021987340  0.012360424
## [3,] -0.003822570  0.023248278
## [4,]  0.033592541  0.008163455
## [5,]  0.006445345 -0.005970114
## [6,] -0.004545320  0.041201578
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:30:40 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## CAT & -0.0007 & 0.0214 & 0.9448 & 0.7349 & -0.0529 & 0.9681 \\ 
##   CVX & 0.0018 & 0.0218 & 0.9188 & 0.7640 & -0.0800 & 1.5185 \\ 
##   KO & -0.0002 & 0.0126 & 0.8711 & 0.7324 & -0.9381 & 4.8018 \\ 
##   LMT & 0.0008 & 0.0161 & 0.9076 & 0.7396 & 0.2200 & 2.2074 \\ 
##   PEP & -0.0000 & 0.0124 & 0.8707 & 0.7342 & -0.8551 & 3.0056 \\ 
##   T & -0.0006 & 0.0173 & 0.8991 & 0.6805 & -0.4807 & 5.8552 \\ 
##   XOM & 0.0026 & 0.0234 & 0.9315 & 0.7837 & -0.3452 & 0.5566 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:30:41 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0837 & 0.1758 & 0.2252 & 0.1287 & 0.1106 & 0.2366 & 0.0395 \\ 
##   2 & 0.2239 & 0.0435 & 0.0719 & 0.1362 & 0.1670 & 0.2179 & 0.1397 \\ 
##   3 & 0.1829 & 0.0455 & 0.1726 & 0.2350 & 0.1352 & 0.1796 & 0.0491 \\ 
##   4 & 0.1989 & 0.1114 & 0.1451 & 0.1802 & 0.1240 & 0.0632 & 0.1772 \\ 
##   5 & 0.1354 & 0.1487 & 0.2160 & 0.0333 & 0.1749 & 0.1123 & 0.1793 \\ 
##   6 & 0.1587 & 0.0645 & 0.1317 & 0.1722 & 0.1025 & 0.1946 & 0.1757 \\ 
##   7 & 0.2874 & 0.1486 & 0.1197 & 0.0188 & 0.2649 & 0.1482 & 0.0125 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:30:41 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0003 & 0.0113 & 0.9400 & 0.7462 & 0.5132 & -0.0648 & 1.1197 \\ 
##   2 & 0.0002 & 0.0120 & 0.9423 & 0.7599 & 0.4921 & -0.0520 & 0.7237 \\ 
##   3 & 0.0001 & 0.0111 & 0.9384 & 0.7585 & 0.5079 & -0.0322 & 0.8370 \\ 
##   4 & 0.0006 & 0.0126 & 0.9448 & 0.7721 & 0.5132 & -0.0300 & 0.6036 \\ 
##   5 & 0.0005 & 0.0123 & 0.9385 & 0.7542 & 0.4868 & -0.0939 & 0.8724 \\ 
##   6 & 0.0004 & 0.0120 & 0.9412 & 0.7658 & 0.4921 & -0.0262 & 0.7300 \\ 
##   7 & -0.0000 & 0.0122 & 0.9435 & 0.7544 & 0.4974 & -0.1040 & 0.9883 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##  11.861   0.180  14.752
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 18
##         CAT     CVX     KO    LMT    PEP       T     XOM   Return  Risk1   Risk2
##       <dbl>   <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>    <dbl>  <dbl>   <dbl>
##  1 0.0916   2.12e-2 0.181  0.239  0.310  0.129   0.0287   1.13e-4 0.0105 0.00420
##  2 0.0196   3.67e-2 0.139  0.307  0.132  0.350   0.0156   9.72e-5 0.0112 0.00373
##  3 0.0529   1.09e-3 0.110  0.228  0.352  0.205   0.0511   1.21e-4 0.0105 0.00405
##  4 0.250    7.59e-4 0.164  0.182  0.0352 0.367   0.00208 -2.83e-4 0.0119 0.00381
##  5 0.00982  8.15e-2 0.300  0.189  0.291  0.0817  0.0467   2.98e-4 0.0105 0.00444
##  6 0.00825  3.56e-1 0.0706 0.0685 0.0999 0.0157  0.381    1.65e-3 0.0172 0.00607
##  7 0.00825  3.56e-1 0.0706 0.0685 0.0999 0.0157  0.381    1.65e-3 0.0172 0.00607
##  8 0.00825  3.56e-1 0.0706 0.0685 0.0999 0.0157  0.381    1.65e-3 0.0172 0.00607
##  9 0.00825  3.56e-1 0.0706 0.0685 0.0999 0.0157  0.381    1.65e-3 0.0172 0.00607
## 10 0.000693 3.01e-1 0.0276 0.257  0.124  0.00793 0.281    1.46e-3 0.0154 0.00542
## # ℹ 8 more variables: Risk3 <dbl>, Risk4 <dbl>, Risk5 <dbl>,
## #   SharpeRatio1 <dbl>, SharpeRatio2 <dbl>, SharpeRatio3 <dbl>,
## #   SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrrrr}
##   \hline
##  & CAT & CVX & KO & LMT & PEP & T & XOM & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.091590 & 0.021227 & 0.181077 & 0.238560 & 0.310188 & 0.128676 & 0.028682 & 0.000113 & 0.010470 & 0.004197 & 0.006903 & 0.002767 & 0.007847 & 0.010780 & 0.026889 & 0.016350 & 0.040784 & 0.014383 \\ 
##   2 & 0.019623 & 0.036713 & 0.138843 & 0.307061 & 0.131743 & 0.350421 & 0.015596 & 0.000097 & 0.011213 & 0.003731 & 0.007412 & 0.002466 & 0.008394 & 0.008671 & 0.026059 & 0.013118 & 0.039424 & 0.011583 \\ 
##   3 & 0.052906 & 0.001093 & 0.110013 & 0.228497 & 0.351543 & 0.204805 & 0.051142 & 0.000121 & 0.010540 & 0.004051 & 0.006882 & 0.002645 & 0.007889 & 0.011474 & 0.029856 & 0.017574 & 0.045730 & 0.015329 \\ 
##   4 & 0.249632 & 0.000759 & 0.163529 & 0.181916 & 0.035162 & 0.366920 & 0.002082 & -0.000283 & 0.011887 & 0.003812 & 0.007612 & 0.002441 & 0.009124 & -0.023840 & -0.074345 & -0.037228 & -0.116098 & -0.031060 \\ 
##   5 & 0.009817 & 0.081509 & 0.299841 & 0.189498 & 0.290903 & 0.081707 & 0.046727 & 0.000298 & 0.010541 & 0.004443 & 0.007058 & 0.002975 & 0.007810 & 0.028308 & 0.067150 & 0.042277 & 0.100288 & 0.038203 \\ 
##   6 & 0.008248 & 0.356324 & 0.070645 & 0.068519 & 0.099944 & 0.015650 & 0.380671 & 0.001650 & 0.017223 & 0.006068 & 0.010489 & 0.003696 & 0.013637 & 0.095828 & 0.271995 & 0.157344 & 0.446600 & 0.121025 \\ 
##   7 & 0.008248 & 0.356324 & 0.070645 & 0.068519 & 0.099944 & 0.015650 & 0.380671 & 0.001650 & 0.017223 & 0.006068 & 0.010489 & 0.003696 & 0.013637 & 0.095828 & 0.271995 & 0.157344 & 0.446600 & 0.121025 \\ 
##   8 & 0.008248 & 0.356324 & 0.070645 & 0.068519 & 0.099944 & 0.015650 & 0.380671 & 0.001650 & 0.017223 & 0.006068 & 0.010489 & 0.003696 & 0.013637 & 0.095828 & 0.271995 & 0.157344 & 0.446600 & 0.121025 \\ 
##   9 & 0.008248 & 0.356324 & 0.070645 & 0.068519 & 0.099944 & 0.015650 & 0.380671 & 0.001650 & 0.017223 & 0.006068 & 0.010489 & 0.003696 & 0.013637 & 0.095828 & 0.271995 & 0.157344 & 0.446600 & 0.121025 \\ 
##   10 & 0.000693 & 0.301378 & 0.027589 & 0.257330 & 0.124072 & 0.007935 & 0.281004 & 0.001460 & 0.015425 & 0.005421 & 0.009708 & 0.003412 & 0.011987 & 0.094627 & 0.269250 & 0.150359 & 0.427828 & 0.121767 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.09159 & 0.01962 & 0.05291 & 0.24963 & 0.00982 \\ 
##   2 & 0.02123 & 0.03671 & 0.00109 & 0.00076 & 0.08151 \\ 
##   3 & 0.18108 & 0.13884 & 0.11001 & 0.16353 & 0.29984 \\ 
##   4 & 0.23856 & 0.30706 & 0.22850 & 0.18192 & 0.18950 \\ 
##   5 & 0.31019 & 0.13174 & 0.35154 & 0.03516 & 0.29090 \\ 
##   6 & 0.12868 & 0.35042 & 0.20481 & 0.36692 & 0.08171 \\ 
##   7 & 0.02868 & 0.01560 & 0.05114 & 0.00208 & 0.04673 \\ 
##   8 & 0.02844 & 0.02450 & 0.03048 & -0.07142 & 0.07519 \\ 
##   9 & 0.16621 & 0.05923 & 0.10924 & 0.03875 & 0.12399 \\ 
##   10 & 0.17113 & 0.41368 & 0.27898 & -1.84299 & 0.60645 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.00825 & 0.00825 & 0.00825 & 0.00825 & 0.00069 \\ 
##   2 & 0.35632 & 0.35632 & 0.35632 & 0.35632 & 0.30138 \\ 
##   3 & 0.07064 & 0.07064 & 0.07064 & 0.07064 & 0.02759 \\ 
##   4 & 0.06852 & 0.06852 & 0.06852 & 0.06852 & 0.25733 \\ 
##   5 & 0.09994 & 0.09994 & 0.09994 & 0.09994 & 0.12407 \\ 
##   6 & 0.01565 & 0.01565 & 0.01565 & 0.01565 & 0.00793 \\ 
##   7 & 0.38067 & 0.38067 & 0.38067 & 0.38067 & 0.28100 \\ 
##   8 & 0.41591 & 0.41591 & 0.41591 & 0.41591 & 0.36784 \\ 
##   9 & 0.27340 & 0.09632 & 0.16651 & 0.05866 & 0.19029 \\ 
##   10 & 1.52122 & 4.31778 & 2.49776 & 7.08956 & 1.93300 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & PEP & 0.3102 & T & 0.3504 & PEP & 0.3515 & T & 0.3669 & KO & 0.2998 & XOM & 0.3807 & XOM & 0.3807 & XOM & 0.3807 & XOM & 0.3807 & CVX & 0.3014 \\ 
##   2 & LMT & 0.2386 & LMT & 0.3071 & LMT & 0.2285 & CAT & 0.2496 & PEP & 0.2909 & CVX & 0.3563 & CVX & 0.3563 & CVX & 0.3563 & CVX & 0.3563 & XOM & 0.2810 \\ 
##   3 & KO & 0.1811 & KO & 0.1388 & T & 0.2048 & LMT & 0.1819 & LMT & 0.1895 & PEP & 0.0999 & PEP & 0.0999 & PEP & 0.0999 & PEP & 0.0999 & LMT & 0.2573 \\ 
##   4 & T & 0.1287 & PEP & 0.1317 & KO & 0.1100 & KO & 0.1635 & T & 0.0817 & KO & 0.0706 & KO & 0.0706 & KO & 0.0706 & KO & 0.0706 & PEP & 0.1241 \\ 
##   5 & CAT & 0.0916 & CVX & 0.0367 & CAT & 0.0529 & PEP & 0.0352 & CVX & 0.0815 & LMT & 0.0685 & LMT & 0.0685 & LMT & 0.0685 & LMT & 0.0685 & KO & 0.0276 \\ 
##   6 & XOM & 0.0287 & CAT & 0.0196 & XOM & 0.0511 & XOM & 0.0021 & XOM & 0.0467 & T & 0.0157 & T & 0.0157 & T & 0.0157 & T & 0.0157 & T & 0.0079 \\ 
##   7 & CVX & 0.0212 & XOM & 0.0156 & CVX & 0.0011 & CVX & 0.0008 & CAT & 0.0098 & CAT & 0.0082 & CAT & 0.0082 & CAT & 0.0082 & CAT & 0.0082 & CAT & 0.0007 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 18
##         CAT      CVX     KO    LMT    PEP       T     XOM  Return Risk1  Risk2
##       <dbl>    <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>   <dbl> <dbl>  <dbl>
##  1 0.0916   0.0212   0.181  0.239  0.310  0.129   0.0287   0.0284 0.166 0.0666
##  2 0.0196   0.0367   0.139  0.307  0.132  0.350   0.0156   0.0245 0.178 0.0592
##  3 0.0529   0.00109  0.110  0.228  0.352  0.205   0.0511   0.0305 0.167 0.0643
##  4 0.250    0.000759 0.164  0.182  0.0352 0.367   0.00208 -0.0714 0.189 0.0605
##  5 0.00982  0.0815   0.300  0.189  0.291  0.0817  0.0467   0.0752 0.167 0.0705
##  6 0.00825  0.356    0.0706 0.0685 0.0999 0.0157  0.381    0.416  0.273 0.0963
##  7 0.00825  0.356    0.0706 0.0685 0.0999 0.0157  0.381    0.416  0.273 0.0963
##  8 0.00825  0.356    0.0706 0.0685 0.0999 0.0157  0.381    0.416  0.273 0.0963
##  9 0.00825  0.356    0.0706 0.0685 0.0999 0.0157  0.381    0.416  0.273 0.0963
## 10 0.000693 0.301    0.0276 0.257  0.124  0.00793 0.281    0.368  0.245 0.0861
## # ℹ 8 more variables: Risk3 <dbl>, Risk4 <dbl>, Risk5 <dbl>,
## #   SharpeRatio1 <dbl>, SharpeRatio2 <dbl>, SharpeRatio3 <dbl>,
## #   SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2022-01-01")
end_date <- as.Date("2022-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - lowest average risk

CumReturnVolCorr_low_avg_risk <- cumsum(TP2)
CumReturnVolCorr_low_avg_risk
##  [1]  0.013534662  0.005525953 -0.008153377 -0.010593899 -0.005297540
##  [6]  0.031454520  0.003552513  0.015892711  0.028364752  0.050914012
## [11]  0.052974901  0.073446677  0.081536510  0.085411702  0.096164065
## [16]  0.101239839  0.122435881  0.123156783  0.128869481  0.110810119
## [21]  0.121293862  0.131090879  0.141978713  0.144066367  0.109058763
## [26]  0.127133950  0.144224156  0.143826616  0.150060511  0.140409509
## [31]  0.144005057  0.140437189  0.136780441  0.157360696  0.153031204
## [36]  0.150512958  0.128214237  0.135508804  0.146987720  0.144272215
## [41]  0.140352381  0.117660727  0.096317776  0.096680125  0.103311814
## [46]  0.087208673  0.102468817  0.113614247  0.108562590  0.098187167
## [51]  0.090849124  0.095114824  0.107257099  0.118682933  0.103165278
## [56]  0.126114783  0.137312891  0.123725609  0.130621405  0.135558604

Portfolio selected from DD_AP_2022_lowest_risk

#Import data

DD_AP_2022_lowest_risk <- read.csv("~/Desktop/PO/AP/DD/2022/DD_AP_2022_lowest_risk.csv")

#remove the date column
asset_prices<-DD_AP_2022_lowest_risk[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##           CVX      JNJ       KO      LMT      PEP        T      XOM
## [1,] 4.675349 5.065812 3.999863 5.798051 5.075427 2.771057 4.053835
## [2,] 4.693381 5.063127 4.016420 5.819354 5.076872 2.779281 4.090759
## [3,] 4.699866 5.069768 4.024679 5.808661 5.080272 2.801268 4.103119
## [4,] 4.708339 5.066336 4.019401 5.808270 5.080502 2.797446 4.126368
## [5,] 4.722597 5.079763 4.017083 5.814230 5.081767 2.831038 4.134531
## [6,] 4.723237 5.074807 4.018739 5.822829 5.082283 2.837484 4.128561
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##               CVX          JNJ            KO           LMT           PEP
## [1,] 0.0180319769 -0.002684952  0.0165567763  0.0213032350  0.0014442648
## [2,] 0.0064847584  0.006641478  0.0082591279 -0.0106927108  0.0034000998
## [3,] 0.0084732955 -0.003431733 -0.0052779119 -0.0003909202  0.0002301584
## [4,] 0.0142577441  0.013426653 -0.0023177719  0.0059599532  0.0012645463
## [5,] 0.0006396038 -0.004955970  0.0016560014  0.0085983597  0.0005167721
## [6,] 0.0226024268 -0.010687310  0.0003307344  0.0024471583 -0.0004594556
##                 T          XOM
## [1,]  0.008223900  0.036924179
## [2,]  0.021987340  0.012360424
## [3,] -0.003822570  0.023248278
## [4,]  0.033592541  0.008163455
## [5,]  0.006445345 -0.005970114
## [6,] -0.004545320  0.041201578
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:22 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## CVX & 0.0018 & 0.0218 & 0.9188 & 0.7640 & -0.0800 & 1.5185 \\ 
##   JNJ & -0.0000 & 0.0115 & 0.8973 & 0.7742 & 0.6441 & 1.3921 \\ 
##   KO & -0.0002 & 0.0126 & 0.8711 & 0.7324 & -0.9381 & 4.8018 \\ 
##   LMT & 0.0008 & 0.0161 & 0.9076 & 0.7396 & 0.2200 & 2.2074 \\ 
##   PEP & -0.0000 & 0.0124 & 0.8707 & 0.7342 & -0.8551 & 3.0056 \\ 
##   T & -0.0006 & 0.0173 & 0.8991 & 0.6805 & -0.4807 & 5.8552 \\ 
##   XOM & 0.0026 & 0.0234 & 0.9315 & 0.7837 & -0.3452 & 0.5566 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:23 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0692 & 0.0647 & 0.1008 & 0.1468 & 0.1119 & 0.2423 & 0.2643 \\ 
##   2 & 0.3189 & 0.0194 & 0.0088 & 0.3176 & 0.1997 & 0.0151 & 0.1205 \\ 
##   3 & 0.1209 & 0.0572 & 0.0215 & 0.3538 & 0.3569 & 0.0775 & 0.0121 \\ 
##   4 & 0.0840 & 0.3448 & 0.0074 & 0.2640 & 0.2069 & 0.0136 & 0.0792 \\ 
##   5 & 0.2398 & 0.1869 & 0.0319 & 0.1842 & 0.0734 & 0.1025 & 0.1814 \\ 
##   6 & 0.2078 & 0.0662 & 0.0518 & 0.1877 & 0.1159 & 0.2243 & 0.1463 \\ 
##   7 & 0.0721 & 0.1187 & 0.1723 & 0.1646 & 0.1730 & 0.1118 & 0.1875 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:23 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0008 & 0.0119 & 0.9374 & 0.7640 & 0.5026 & -0.0400 & 0.7560 \\ 
##   2 & 0.0011 & 0.0135 & 0.9403 & 0.7540 & 0.4709 & 0.0117 & 0.6332 \\ 
##   3 & 0.0005 & 0.0107 & 0.9311 & 0.7397 & 0.4497 & -0.1044 & 0.9545 \\ 
##   4 & 0.0005 & 0.0101 & 0.9218 & 0.7442 & 0.4444 & 0.1276 & 1.0629 \\ 
##   5 & 0.0010 & 0.0124 & 0.9369 & 0.7674 & 0.4974 & 0.0776 & 0.6964 \\ 
##   6 & 0.0008 & 0.0120 & 0.9367 & 0.7603 & 0.4868 & 0.0164 & 0.8496 \\ 
##   7 & 0.0006 & 0.0107 & 0.9321 & 0.7462 & 0.4762 & -0.0032 & 1.0963 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##   9.868   0.155  11.020
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 18
##        CVX   JNJ      KO    LMT     PEP      T    XOM     Return   Risk1   Risk2
##      <dbl> <dbl>   <dbl>  <dbl>   <dbl>  <dbl>  <dbl>      <dbl>   <dbl>   <dbl>
##  1 0.0549  0.418 0.107   0.106  0.204   0.0797 0.0297  0.000177  0.00964 0.00413
##  2 0.00250 0.119 0.164   0.282  0.0374  0.341  0.0539  0.000133  0.0109  0.00362
##  3 0.0864  0.505 0.00352 0.0222 0.184   0.156  0.0419  0.000170  0.00975 0.00424
##  4 0.00132 0.130 0.306   0.211  0.00486 0.326  0.0207 -0.0000256 0.0108  0.00368
##  5 0.0352  0.350 0.0753  0.105  0.236   0.0911 0.108   0.000342  0.00969 0.00393
##  6 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.00172   0.0164  0.00581
##  7 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.00172   0.0164  0.00581
##  8 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.00172   0.0164  0.00581
##  9 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.00172   0.0164  0.00581
## 10 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.00172   0.0164  0.00581
## # ℹ 8 more variables: Risk3 <dbl>, Risk4 <dbl>, Risk5 <dbl>,
## #   SharpeRatio1 <dbl>, SharpeRatio2 <dbl>, SharpeRatio3 <dbl>,
## #   SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:50 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrrrr}
##   \hline
##  & CVX & JNJ & KO & LMT & PEP & T & XOM & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.054899 & 0.418214 & 0.107110 & 0.106354 & 0.204042 & 0.079710 & 0.029671 & 0.000177 & 0.009639 & 0.004127 & 0.006339 & 0.002714 & 0.007253 & 0.018396 & 0.042971 & 0.027974 & 0.065344 & 0.024446 \\ 
##   2 & 0.002496 & 0.119473 & 0.164081 & 0.281913 & 0.037432 & 0.340676 & 0.053929 & 0.000133 & 0.010863 & 0.003625 & 0.007136 & 0.002381 & 0.008164 & 0.012252 & 0.036717 & 0.018650 & 0.055894 & 0.016301 \\ 
##   3 & 0.086394 & 0.505415 & 0.003516 & 0.022228 & 0.184175 & 0.156350 & 0.041922 & 0.000170 & 0.009752 & 0.004245 & 0.006280 & 0.002734 & 0.007437 & 0.017433 & 0.040051 & 0.027069 & 0.062189 & 0.022860 \\ 
##   4 & 0.001318 & 0.129571 & 0.306427 & 0.211490 & 0.004859 & 0.325655 & 0.020679 & -0.000026 & 0.010764 & 0.003683 & 0.006880 & 0.002354 & 0.008252 & -0.002377 & -0.006949 & -0.003720 & -0.010872 & -0.003101 \\ 
##   5 & 0.035244 & 0.349934 & 0.075295 & 0.104640 & 0.236190 & 0.091104 & 0.107594 & 0.000342 & 0.009689 & 0.003935 & 0.006427 & 0.002610 & 0.007233 & 0.035261 & 0.086819 & 0.053158 & 0.130886 & 0.047231 \\ 
##   6 & 0.007354 & 0.168287 & 0.042785 & 0.025712 & 0.073065 & 0.024118 & 0.658679 & 0.001716 & 0.016407 & 0.005808 & 0.010109 & 0.003578 & 0.012915 & 0.104557 & 0.295369 & 0.169706 & 0.479412 & 0.132834 \\ 
##   7 & 0.007354 & 0.168287 & 0.042785 & 0.025712 & 0.073065 & 0.024118 & 0.658679 & 0.001716 & 0.016407 & 0.005808 & 0.010109 & 0.003578 & 0.012915 & 0.104557 & 0.295369 & 0.169706 & 0.479412 & 0.132834 \\ 
##   8 & 0.007354 & 0.168287 & 0.042785 & 0.025712 & 0.073065 & 0.024118 & 0.658679 & 0.001716 & 0.016407 & 0.005808 & 0.010109 & 0.003578 & 0.012915 & 0.104557 & 0.295369 & 0.169706 & 0.479412 & 0.132834 \\ 
##   9 & 0.007354 & 0.168287 & 0.042785 & 0.025712 & 0.073065 & 0.024118 & 0.658679 & 0.001716 & 0.016407 & 0.005808 & 0.010109 & 0.003578 & 0.012915 & 0.104557 & 0.295369 & 0.169706 & 0.479412 & 0.132834 \\ 
##   10 & 0.007354 & 0.168287 & 0.042785 & 0.025712 & 0.073065 & 0.024118 & 0.658679 & 0.001716 & 0.016407 & 0.005808 & 0.010109 & 0.003578 & 0.012915 & 0.104557 & 0.295369 & 0.169706 & 0.479412 & 0.132834 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:50 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.05490 & 0.00250 & 0.08639 & 0.00132 & 0.03524 \\ 
##   2 & 0.41821 & 0.11947 & 0.50541 & 0.12957 & 0.34993 \\ 
##   3 & 0.10711 & 0.16408 & 0.00352 & 0.30643 & 0.07529 \\ 
##   4 & 0.10635 & 0.28191 & 0.02223 & 0.21149 & 0.10464 \\ 
##   5 & 0.20404 & 0.03743 & 0.18418 & 0.00486 & 0.23619 \\ 
##   6 & 0.07971 & 0.34068 & 0.15635 & 0.32566 & 0.09110 \\ 
##   7 & 0.02967 & 0.05393 & 0.04192 & 0.02068 & 0.10759 \\ 
##   8 & 0.04468 & 0.03354 & 0.04284 & -0.00645 & 0.08609 \\ 
##   9 & 0.15302 & 0.05754 & 0.09970 & 0.03737 & 0.11482 \\ 
##   10 & 0.29202 & 0.58287 & 0.42971 & -0.17259 & 0.74976 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:50 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.00735 & 0.00735 & 0.00735 & 0.00735 & 0.00735 \\ 
##   2 & 0.16829 & 0.16829 & 0.16829 & 0.16829 & 0.16829 \\ 
##   3 & 0.04278 & 0.04278 & 0.04278 & 0.04278 & 0.04278 \\ 
##   4 & 0.02571 & 0.02571 & 0.02571 & 0.02571 & 0.02571 \\ 
##   5 & 0.07306 & 0.07306 & 0.07306 & 0.07306 & 0.07306 \\ 
##   6 & 0.02412 & 0.02412 & 0.02412 & 0.02412 & 0.02412 \\ 
##   7 & 0.65868 & 0.65868 & 0.65868 & 0.65868 & 0.65868 \\ 
##   8 & 0.43231 & 0.43231 & 0.43231 & 0.43231 & 0.43231 \\ 
##   9 & 0.26046 & 0.09220 & 0.16047 & 0.05680 & 0.20501 \\ 
##   10 & 1.65979 & 4.68883 & 2.69399 & 7.61042 & 2.10868 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:50 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & JNJ & 0.4182 & T & 0.3407 & JNJ & 0.5054 & T & 0.3257 & JNJ & 0.3499 & XOM & 0.6587 & XOM & 0.6587 & XOM & 0.6587 & XOM & 0.6587 & XOM & 0.6587 \\ 
##   2 & PEP & 0.2040 & LMT & 0.2819 & PEP & 0.1842 & KO & 0.3064 & PEP & 0.2362 & JNJ & 0.1683 & JNJ & 0.1683 & JNJ & 0.1683 & JNJ & 0.1683 & JNJ & 0.1683 \\ 
##   3 & KO & 0.1071 & KO & 0.1641 & T & 0.1563 & LMT & 0.2115 & XOM & 0.1076 & PEP & 0.0731 & PEP & 0.0731 & PEP & 0.0731 & PEP & 0.0731 & PEP & 0.0731 \\ 
##   4 & LMT & 0.1064 & JNJ & 0.1195 & CVX & 0.0864 & JNJ & 0.1296 & LMT & 0.1046 & KO & 0.0428 & KO & 0.0428 & KO & 0.0428 & KO & 0.0428 & KO & 0.0428 \\ 
##   5 & T & 0.0797 & XOM & 0.0539 & XOM & 0.0419 & XOM & 0.0207 & T & 0.0911 & LMT & 0.0257 & LMT & 0.0257 & LMT & 0.0257 & LMT & 0.0257 & LMT & 0.0257 \\ 
##   6 & CVX & 0.0549 & PEP & 0.0374 & LMT & 0.0222 & PEP & 0.0049 & KO & 0.0753 & T & 0.0241 & T & 0.0241 & T & 0.0241 & T & 0.0241 & T & 0.0241 \\ 
##   7 & XOM & 0.0297 & CVX & 0.0025 & KO & 0.0035 & CVX & 0.0013 & CVX & 0.0352 & CVX & 0.0074 & CVX & 0.0074 & CVX & 0.0074 & CVX & 0.0074 & CVX & 0.0074 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 18
##        CVX   JNJ      KO    LMT     PEP      T    XOM   Return Risk1  Risk2
##      <dbl> <dbl>   <dbl>  <dbl>   <dbl>  <dbl>  <dbl>    <dbl> <dbl>  <dbl>
##  1 0.0549  0.418 0.107   0.106  0.204   0.0797 0.0297  0.0447  0.153 0.0655
##  2 0.00250 0.119 0.164   0.282  0.0374  0.341  0.0539  0.0335  0.172 0.0575
##  3 0.0864  0.505 0.00352 0.0222 0.184   0.156  0.0419  0.0428  0.155 0.0674
##  4 0.00132 0.130 0.306   0.211  0.00486 0.326  0.0207 -0.00645 0.171 0.0585
##  5 0.0352  0.350 0.0753  0.105  0.236   0.0911 0.108   0.0861  0.154 0.0625
##  6 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.432   0.260 0.0922
##  7 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.432   0.260 0.0922
##  8 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.432   0.260 0.0922
##  9 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.432   0.260 0.0922
## 10 0.00735 0.168 0.0428  0.0257 0.0731  0.0241 0.659   0.432   0.260 0.0922
## # ℹ 8 more variables: Risk3 <dbl>, Risk4 <dbl>, Risk5 <dbl>,
## #   SharpeRatio1 <dbl>, SharpeRatio2 <dbl>, SharpeRatio3 <dbl>,
## #   SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2022-01-01")
end_date <- as.Date("2022-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - empcor network portfolio

CumReturnVolCorr_low_risk <- cumsum(TP2)
CumReturnVolCorr_low_risk
##  [1]  0.0133838229  0.0036389136 -0.0102313358 -0.0130538790 -0.0077554030
##  [6]  0.0223440359  0.0002968974  0.0147056605  0.0196157522  0.0373717213
## [11]  0.0393761014  0.0579396013  0.0687267063  0.0657560516  0.0765593338
## [16]  0.0796092986  0.1050466146  0.1037408938  0.1091051822  0.0911336152
## [21]  0.1000787752  0.1088869738  0.1194218551  0.1231810359  0.0898929559
## [26]  0.1054061011  0.1188459011  0.1223757392  0.1276793580  0.1217859766
## [31]  0.1252565489  0.1218691627  0.1182615815  0.1386384484  0.1359511576
## [36]  0.1336529450  0.1132704369  0.1162067695  0.1257041097  0.1237155452
## [41]  0.1189464503  0.0983972282  0.0769523281  0.0768417569  0.0826288914
## [46]  0.0746037660  0.0942338974  0.1023224051  0.0977221896  0.0865157236
## [51]  0.0800471708  0.0825171993  0.0927779386  0.1046341822  0.0894664873
## [56]  0.1086034361  0.1187015035  0.1056555350  0.1124086651  0.1173900689

Portfolio selected from DD_AP_2022_highest_mean

DD_AP_2022_highest_mean <- read.csv("~/Desktop/PO/AP/DD/2022/DD_AP_2022_highest_mean.csv")

#remove the date column
asset_prices<-DD_AP_2022_highest_mean[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##           CAT      CVX       KO      LMT      PEP      SLB      XOM
## [1,] 5.276894 4.675349 3.999863 5.798051 5.075427 3.404496 4.053835
## [2,] 5.329037 4.693381 4.016420 5.819354 5.076872 3.451904 4.090759
## [3,] 5.336666 4.699866 4.024679 5.808661 5.080272 3.451904 4.103119
## [4,] 5.346808 4.708339 4.019401 5.808270 5.080502 3.475379 4.126368
## [5,] 5.356669 4.722597 4.017083 5.814230 5.081767 3.503754 4.134531
## [6,] 5.345230 4.723237 4.018739 5.822829 5.082283 3.506319 4.128561
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##               CAT          CVX            KO           LMT           PEP
## [1,]  0.052143013 0.0180319769  0.0165567763  0.0213032350  0.0014442648
## [2,]  0.007628658 0.0064847584  0.0082591279 -0.0106927108  0.0034000998
## [3,]  0.010141792 0.0084732955 -0.0052779119 -0.0003909202  0.0002301584
## [4,]  0.009861644 0.0142577441 -0.0023177719  0.0059599532  0.0012645463
## [5,] -0.011439448 0.0006396038  0.0016560014  0.0085983597  0.0005167721
## [6,] -0.007654317 0.0226024268  0.0003307344  0.0024471583 -0.0004594556
##              SLB          XOM
## [1,] 0.047407924  0.036924179
## [2,] 0.000000000  0.012360424
## [3,] 0.023474816  0.023248278
## [4,] 0.028374850  0.008163455
## [5,] 0.002565774 -0.005970114
## [6,] 0.037993724  0.041201578
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:54 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## CAT & -0.0007 & 0.0214 & 0.9448 & 0.7349 & -0.0529 & 0.9681 \\ 
##   CVX & 0.0018 & 0.0218 & 0.9188 & 0.7640 & -0.0800 & 1.5185 \\ 
##   KO & -0.0002 & 0.0126 & 0.8711 & 0.7324 & -0.9381 & 4.8018 \\ 
##   LMT & 0.0008 & 0.0161 & 0.9076 & 0.7396 & 0.2200 & 2.2074 \\ 
##   PEP & -0.0000 & 0.0124 & 0.8707 & 0.7342 & -0.8551 & 3.0056 \\ 
##   SLB & 0.0018 & 0.0323 & 0.9212 & 0.7910 & -0.2787 & 0.4009 \\ 
##   XOM & 0.0026 & 0.0234 & 0.9315 & 0.7837 & -0.3452 & 0.5566 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:54 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.1849 & 0.1072 & 0.1387 & 0.0699 & 0.1815 & 0.2003 & 0.1176 \\ 
##   2 & 0.2375 & 0.1461 & 0.2329 & 0.0623 & 0.1711 & 0.0192 & 0.1308 \\ 
##   3 & 0.1707 & 0.1691 & 0.0599 & 0.1402 & 0.2022 & 0.0393 & 0.2186 \\ 
##   4 & 0.0087 & 0.3195 & 0.0132 & 0.1135 & 0.1330 & 0.3104 & 0.1017 \\ 
##   5 & 0.1489 & 0.1144 & 0.2119 & 0.0328 & 0.0732 & 0.2054 & 0.2133 \\ 
##   6 & 0.0431 & 0.2159 & 0.0744 & 0.1682 & 0.3041 & 0.1151 & 0.0793 \\ 
##   7 & 0.1066 & 0.0622 & 0.1801 & 0.0277 & 0.0419 & 0.3367 & 0.2447 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:31:54 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0007 & 0.0154 & 0.9378 & 0.7805 & 0.4762 & -0.2076 & 0.4441 \\ 
##   2 & 0.0005 & 0.0129 & 0.9429 & 0.7611 & 0.4868 & -0.1083 & 0.7179 \\ 
##   3 & 0.0009 & 0.0142 & 0.9409 & 0.7797 & 0.4868 & -0.1183 & 0.4253 \\ 
##   4 & 0.0015 & 0.0195 & 0.9279 & 0.7778 & 0.4709 & -0.3566 & 0.5495 \\ 
##   5 & 0.0010 & 0.0166 & 0.9276 & 0.7781 & 0.4868 & -0.2567 & 0.3900 \\ 
##   6 & 0.0009 & 0.0133 & 0.9384 & 0.7555 & 0.4656 & -0.2082 & 0.7604 \\ 
##   7 & 0.0013 & 0.0193 & 0.9225 & 0.7841 & 0.4974 & -0.3185 & 0.3711 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##  10.190   0.118  13.760
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 18
##         CAT    CVX     KO   LMT    PEP     SLB     XOM   Return  Risk1   Risk2
##       <dbl>  <dbl>  <dbl> <dbl>  <dbl>   <dbl>   <dbl>    <dbl>  <dbl>   <dbl>
##  1 0.162    0.0247 0.255  0.243 0.288  0.00868 0.0182  0.000123 0.0108 0.00447
##  2 0.147    0.103  0.0156 0.416 0.303  0.00648 0.00903 0.000425 0.0116 0.00374
##  3 0.162    0.0247 0.255  0.243 0.288  0.00868 0.0182  0.000123 0.0108 0.00447
##  4 0.147    0.103  0.0156 0.416 0.303  0.00648 0.00903 0.000425 0.0116 0.00374
##  5 0.0682   0.143  0.0610 0.165 0.546  0.0126  0.00491 0.000338 0.0108 0.00455
##  6 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.00183  0.0183 0.00659
##  7 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.00183  0.0183 0.00659
##  8 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.00183  0.0183 0.00659
##  9 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.00183  0.0183 0.00659
## 10 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.00183  0.0183 0.00659
## # ℹ 8 more variables: Risk3 <dbl>, Risk4 <dbl>, Risk5 <dbl>,
## #   SharpeRatio1 <dbl>, SharpeRatio2 <dbl>, SharpeRatio3 <dbl>,
## #   SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:32:24 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrrrr}
##   \hline
##  & CAT & CVX & KO & LMT & PEP & SLB & XOM & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.162155 & 0.024744 & 0.255436 & 0.243218 & 0.287587 & 0.008684 & 0.018176 & 0.000123 & 0.010766 & 0.004472 & 0.007196 & 0.002989 & 0.008002 & 0.011446 & 0.027554 & 0.017124 & 0.041224 & 0.015399 \\ 
##   2 & 0.147364 & 0.102705 & 0.015579 & 0.416283 & 0.302555 & 0.006480 & 0.009034 & 0.000425 & 0.011586 & 0.003743 & 0.007702 & 0.002488 & 0.008649 & 0.036649 & 0.113447 & 0.055128 & 0.170648 & 0.049094 \\ 
##   3 & 0.162155 & 0.024744 & 0.255436 & 0.243218 & 0.287587 & 0.008684 & 0.018176 & 0.000123 & 0.010766 & 0.004472 & 0.007196 & 0.002989 & 0.008002 & 0.011446 & 0.027554 & 0.017124 & 0.041224 & 0.015399 \\ 
##   4 & 0.147364 & 0.102705 & 0.015579 & 0.416283 & 0.302555 & 0.006480 & 0.009034 & 0.000425 & 0.011586 & 0.003743 & 0.007702 & 0.002488 & 0.008649 & 0.036649 & 0.113447 & 0.055128 & 0.170648 & 0.049094 \\ 
##   5 & 0.068205 & 0.142617 & 0.060968 & 0.165061 & 0.545656 & 0.012585 & 0.004907 & 0.000338 & 0.010786 & 0.004546 & 0.007293 & 0.003074 & 0.007922 & 0.031314 & 0.074294 & 0.046316 & 0.109887 & 0.042634 \\ 
##   6 & 0.000555 & 0.233347 & 0.068392 & 0.154910 & 0.026411 & 0.045046 & 0.471340 & 0.001832 & 0.018271 & 0.006591 & 0.011173 & 0.004031 & 0.014451 & 0.100250 & 0.277898 & 0.163934 & 0.454431 & 0.126748 \\ 
##   7 & 0.000555 & 0.233347 & 0.068392 & 0.154910 & 0.026411 & 0.045046 & 0.471340 & 0.001832 & 0.018271 & 0.006591 & 0.011173 & 0.004031 & 0.014451 & 0.100250 & 0.277898 & 0.163934 & 0.454431 & 0.126748 \\ 
##   8 & 0.000555 & 0.233347 & 0.068392 & 0.154910 & 0.026411 & 0.045046 & 0.471340 & 0.001832 & 0.018271 & 0.006591 & 0.011173 & 0.004031 & 0.014451 & 0.100250 & 0.277898 & 0.163934 & 0.454431 & 0.126748 \\ 
##   9 & 0.000555 & 0.233347 & 0.068392 & 0.154910 & 0.026411 & 0.045046 & 0.471340 & 0.001832 & 0.018271 & 0.006591 & 0.011173 & 0.004031 & 0.014451 & 0.100250 & 0.277898 & 0.163934 & 0.454431 & 0.126748 \\ 
##   10 & 0.000555 & 0.233347 & 0.068392 & 0.154910 & 0.026411 & 0.045046 & 0.471340 & 0.001832 & 0.018271 & 0.006591 & 0.011173 & 0.004031 & 0.014451 & 0.100250 & 0.277898 & 0.163934 & 0.454431 & 0.126748 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:32:24 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.16216 & 0.14736 & 0.16216 & 0.14736 & 0.06821 \\ 
##   2 & 0.02474 & 0.10271 & 0.02474 & 0.10271 & 0.14262 \\ 
##   3 & 0.25544 & 0.01558 & 0.25544 & 0.01558 & 0.06097 \\ 
##   4 & 0.24322 & 0.41628 & 0.24322 & 0.41628 & 0.16506 \\ 
##   5 & 0.28759 & 0.30256 & 0.28759 & 0.30256 & 0.54566 \\ 
##   6 & 0.00868 & 0.00648 & 0.00868 & 0.00648 & 0.01258 \\ 
##   7 & 0.01818 & 0.00903 & 0.01818 & 0.00903 & 0.00491 \\ 
##   8 & 0.03105 & 0.10700 & 0.03105 & 0.10700 & 0.08512 \\ 
##   9 & 0.17091 & 0.05941 & 0.11424 & 0.03950 & 0.12576 \\ 
##   10 & 0.18170 & 1.80091 & 0.27184 & 2.70895 & 0.67679 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:32:24 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.00056 & 0.00056 & 0.00056 & 0.00056 & 0.00056 \\ 
##   2 & 0.23335 & 0.23335 & 0.23335 & 0.23335 & 0.23335 \\ 
##   3 & 0.06839 & 0.06839 & 0.06839 & 0.06839 & 0.06839 \\ 
##   4 & 0.15491 & 0.15491 & 0.15491 & 0.15491 & 0.15491 \\ 
##   5 & 0.02641 & 0.02641 & 0.02641 & 0.02641 & 0.02641 \\ 
##   6 & 0.04505 & 0.04505 & 0.04505 & 0.04505 & 0.04505 \\ 
##   7 & 0.47134 & 0.47134 & 0.47134 & 0.47134 & 0.47134 \\ 
##   8 & 0.46158 & 0.46158 & 0.46158 & 0.46158 & 0.46158 \\ 
##   9 & 0.29004 & 0.10463 & 0.17737 & 0.06399 & 0.22941 \\ 
##   10 & 1.59142 & 4.41150 & 2.60236 & 7.21387 & 2.01206 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 12:32:24 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & PEP & 0.2876 & LMT & 0.4163 & PEP & 0.2876 & LMT & 0.4163 & PEP & 0.5457 & XOM & 0.4713 & XOM & 0.4713 & XOM & 0.4713 & XOM & 0.4713 & XOM & 0.4713 \\ 
##   2 & KO & 0.2554 & PEP & 0.3026 & KO & 0.2554 & PEP & 0.3026 & LMT & 0.1651 & CVX & 0.2333 & CVX & 0.2333 & CVX & 0.2333 & CVX & 0.2333 & CVX & 0.2333 \\ 
##   3 & LMT & 0.2432 & CAT & 0.1474 & LMT & 0.2432 & CAT & 0.1474 & CVX & 0.1426 & LMT & 0.1549 & LMT & 0.1549 & LMT & 0.1549 & LMT & 0.1549 & LMT & 0.1549 \\ 
##   4 & CAT & 0.1622 & CVX & 0.1027 & CAT & 0.1622 & CVX & 0.1027 & CAT & 0.0682 & KO & 0.0684 & KO & 0.0684 & KO & 0.0684 & KO & 0.0684 & KO & 0.0684 \\ 
##   5 & CVX & 0.0247 & KO & 0.0156 & CVX & 0.0247 & KO & 0.0156 & KO & 0.0610 & SLB & 0.0450 & SLB & 0.0450 & SLB & 0.0450 & SLB & 0.0450 & SLB & 0.0450 \\ 
##   6 & XOM & 0.0182 & XOM & 0.0090 & XOM & 0.0182 & XOM & 0.0090 & SLB & 0.0126 & PEP & 0.0264 & PEP & 0.0264 & PEP & 0.0264 & PEP & 0.0264 & PEP & 0.0264 \\ 
##   7 & SLB & 0.0087 & SLB & 0.0065 & SLB & 0.0087 & SLB & 0.0065 & XOM & 0.0049 & CAT & 0.0006 & CAT & 0.0006 & CAT & 0.0006 & CAT & 0.0006 & CAT & 0.0006 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 18
##         CAT    CVX     KO   LMT    PEP     SLB     XOM Return Risk1  Risk2 Risk3
##       <dbl>  <dbl>  <dbl> <dbl>  <dbl>   <dbl>   <dbl>  <dbl> <dbl>  <dbl> <dbl>
##  1 0.162    0.0247 0.255  0.243 0.288  0.00868 0.0182  0.0311 0.171 0.0710 0.114
##  2 0.147    0.103  0.0156 0.416 0.303  0.00648 0.00903 0.107  0.184 0.0594 0.122
##  3 0.162    0.0247 0.255  0.243 0.288  0.00868 0.0182  0.0311 0.171 0.0710 0.114
##  4 0.147    0.103  0.0156 0.416 0.303  0.00648 0.00903 0.107  0.184 0.0594 0.122
##  5 0.0682   0.143  0.0610 0.165 0.546  0.0126  0.00491 0.0851 0.171 0.0722 0.116
##  6 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.462  0.290 0.105  0.177
##  7 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.462  0.290 0.105  0.177
##  8 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.462  0.290 0.105  0.177
##  9 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.462  0.290 0.105  0.177
## 10 0.000555 0.233  0.0684 0.155 0.0264 0.0450  0.471   0.462  0.290 0.105  0.177
## # ℹ 7 more variables: Risk4 <dbl>, Risk5 <dbl>, SharpeRatio1 <dbl>,
## #   SharpeRatio2 <dbl>, SharpeRatio3 <dbl>, SharpeRatio4 <dbl>,
## #   SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2022-01-01")
end_date <- as.Date("2022-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - highest mean

CumReturnVolCorr_high_mean <- cumsum(TP2)
CumReturnVolCorr_high_mean
##  [1]  0.0161359746  0.0103188034 -0.0023992285 -0.0061095104 -0.0062710597
##  [6]  0.0288963810 -0.0009180627  0.0127580339  0.0309154032  0.0567375660
## [11]  0.0590902472  0.0832917234  0.0917076385  0.0938749193  0.1035626444
## [16]  0.1093160312  0.1309511653  0.1334755328  0.1387534413  0.1214755021
## [21]  0.1326982786  0.1416345936  0.1541700450  0.1571682650  0.1213371081
## [26]  0.1374305585  0.1517263067  0.1511371329  0.1583713281  0.1478574363
## [31]  0.1516399926  0.1486847312  0.1436990934  0.1643496294  0.1589089135
## [36]  0.1567425022  0.1348530316  0.1424015145  0.1526659602  0.1494531206
## [41]  0.1490716538  0.1261479194  0.1043839690  0.1023694020  0.1092319726
## [46]  0.0937494947  0.1117474309  0.1219561221  0.1178511107  0.1078617193
## [51]  0.1013309928  0.1057051711  0.1194326638  0.1313560368  0.1133661684
## [56]  0.1364312270  0.1475981287  0.1340473659  0.1413178220  0.1473301595

Merge and create a new dataframe for Without and With clustering

# Example data
CumReturnVolCorr <- data.frame(
  Date = as.character(TestDates),
  low_avg_risk = CumReturnVolCorr_low_avg_risk,
  low_risk = CumReturnVolCorr_low_risk,
  high_mean = CumReturnVolCorr_high_mean
)

Plot

library(ggplot2)

# Create the plot with date interval
ggplot(data = CumReturnVolCorr, aes(x = as.Date(Date))) +
  geom_line(aes(y = low_avg_risk, color = "low_avg_risk"), lwd = 1.5) +
  geom_line(aes(y = low_risk, color = "low_risk"), lwd = 1.5) +
  geom_line(aes(y = high_mean, color = "high_mean"), lwd = 1.5) + 
  labs(y = "Cumulative Return",
       x = "Date") +
  scale_color_manual(name = "Data",
                     values = c("low_avg_risk" = "blue", 
                                "low_risk" = "red", 
                                "high_mean" = "green"), # Add color for the new series
                     labels = c("low_avg_risk" = "lowest average risk", 
                                "low_risk" = "lowest risk", 
                                "high_mean" = "highest mean")) + # Adjust labels
  scale_x_date(date_breaks = "1 month", date_labels = "%Y-%m") + # Show dates at monthly intervals
  theme_minimal()